import { Colors } from "./color";
import * as THREE from 'three';
import DataBus from './databus';

import Sea from './Sea';
import Sky from './Sky';
import EnnemyHolder from './Ennemy';
import AirPlane from './AirPlane';
import CoinsHolder from './Coin';
import ParticlesHolder from './Particle';


const databus = new DataBus()
const mousePos = { x: 0, y: 0 }; // 当前鼠标

let game = databus.game
let HEIGHT = window.innerHeight; // 浏览器高度
let WIDTH = window.innerWidth; // 浏览器宽度位置


export default class Main {
	constructor() {
		databus.reset(); // 初始化数据

		this.init();
	}

	// 初始化游戏
	init() {
		this.addEventListener(); // 添加交互监听

		// DOM
		this.fieldDistance = document.getElementById("distValue");
		this.energyBar = document.getElementById("energyBar");
		this.replayMessage = document.getElementById("replayMessage");
		this.fieldLevel = document.getElementById("levelValue");
		this.levelCircle = document.getElementById("levelCircleStroke");
		this.gameFps = document.getElementById("gameFps");

		this.fieldLevel.innerHTML = Math.floor(game.level);

		this.Scene(); // 创建场景和摄像机
		this.createLights(); // 创建灯光

		this.airplane = new AirPlane(); // 创建飞机
		this.sea = new Sea(); // 创建海洋
		this.sky = new Sky(); // 创建天空
		this.coinsHolder = new CoinsHolder(); // 创建硬币合集
		this.ennemiesHolder = new EnnemyHolder(); // 创建石头合集
		this.particlesHolder = new ParticlesHolder(); // 创建破碎特效
		this.scene.add(this.sea.mesh);
		this.scene.add(this.airplane.mesh);
		this.scene.add(this.sky.mesh);
		this.scene.add(this.coinsHolder.mesh);
		this.scene.add(this.ennemiesHolder.mesh);
		this.scene.add(this.particlesHolder.mesh);

		// 开始循环
		this.loop();
	}

	// 交互监听
	addEventListener() {
		const _this = this
		// 重开游戏
		function replay() {
			if (game.status === "waitingReplay") {
				databus.resetGame(); // 重新开始，数据初始化
				_this.replayMessage.style.display = "none";
				_this.fieldLevel.innerHTML = Math.floor(game.level);
				game = databus.game
			}
		}
		function mouseMove(event) {
			mousePos.x = 1 - event.clientX / WIDTH * 2; // 值为-1至1，x轴的位置
			mousePos.y = 1 - event.clientY / HEIGHT * 2; // 值为-1至1，y轴的位置
		}
		function touchMove(event) {
			event.preventDefault();
			mousePos.x = 1 - event.touches[0].pageX / WIDTH * 2;
			mousePos.y = 1 - event.touches[0].pageY / HEIGHT * 2;
		}

		window.addEventListener('mousemove', mouseMove, false);
		window.addEventListener('touchmove', touchMove, false);
		window.addEventListener('touchstart', (e) => e.preventDefault(), false);
		window.addEventListener('mouseup', replay, false);
		window.addEventListener('touchend', replay, false);
	}

	// 创建场景和摄像机
	Scene() {
		this.scene = new THREE.Scene(); // 场景
		// 场景添加 淡黄色雾（雾覆盖位置：100~950）
		this.scene.fog = new THREE.Fog(0xf7d9aa, 100, 950);

		// 设置摄像机位置（初始位置：x=0,y=100,z=200）
		let camera = new THREE.PerspectiveCamera(50, WIDTH / HEIGHT, .1, 10000);
		camera.position.x = 0;
		camera.position.z = 200;
		camera.position.y = game.planeDefaultHeight;
		this.camera = camera; // 摄像机

		let renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
		renderer.setSize(WIDTH, HEIGHT);
		renderer.shadowMap.enabled = true;
		let container = document.getElementById('world');
		container.appendChild(renderer.domElement);
		this.renderer = renderer; // 渲染器

		// 浏览器缩放，重新设置渲染器宽高和摄像机位置
		window.addEventListener('resize', () => {
			HEIGHT = window.innerHeight;
			WIDTH = window.innerWidth;
			this.renderer.setSize(WIDTH, HEIGHT);
			this.camera.aspect = WIDTH / HEIGHT;
			this.camera.updateProjectionMatrix();
		}, false);
	}

	// 创建灯光
	createLights() {
		// 半球光，全体加亮度（从上往下，无阴影）
		const hemisphereLight = new THREE.HemisphereLight(0xaaaaaa, 0x000000, .9)

		// 平行光，添加阴影（光源位置，上前右）
		let shadowLight = new THREE.DirectionalLight(0xffffff, .9);
		shadowLight.position.set(150, 350, 350);
		shadowLight.castShadow = true;
		// 阴影投射范围
		shadowLight.shadow.camera.left = -400;
		shadowLight.shadow.camera.right = 400;
		shadowLight.shadow.camera.top = 400;
		shadowLight.shadow.camera.bottom = -400;
		shadowLight.shadow.camera.near = 1;
		shadowLight.shadow.camera.far = 1000;
		// 阴影显示清晰度
		shadowLight.shadow.mapSize.width = 4096;
		shadowLight.shadow.mapSize.height = 4096;

		// 环境光（均匀的照亮场景中的所有物体）
		this.ambientLight = new THREE.AmbientLight(0xdc8874, .5);

		this.scene.add(hemisphereLight);
		this.scene.add(shadowLight);
		this.scene.add(this.ambientLight);
	}

	// 更新飞行状态
	updatePlane() {
		const airplane = this.airplane
		const camera = this.camera

		// 飞机加速度
		game.planeSpeed = normalize(-mousePos.x, -.5, .5, game.planeMinSpeed, game.planeMaxSpeed);
		// height: 20-180
		let targetY = normalize(mousePos.y, -.75, .75, game.planeDefaultHeight - game.planeAmpHeight, game.planeDefaultHeight + game.planeAmpHeight);
		// width: -7.5至-90
		let targetX = normalize(mousePos.x, -1, 1, -game.planeAmpWidth * .1, -game.planeAmpWidth * 1.2);

		// 飞机碰撞造成的飞机偏移
		game.planeCollisionDisplacementX += game.planeCollisionSpeedX;
		targetX += game.planeCollisionDisplacementX;

		game.planeCollisionDisplacementY += game.planeCollisionSpeedY;
		targetY += game.planeCollisionDisplacementY;

		// 飞机跟随鼠标移动
		airplane.mesh.position.y += (targetY - airplane.mesh.position.y) * game.planeMoveSensivity;
		airplane.mesh.position.x += (targetX - airplane.mesh.position.x) * game.planeMoveSensivity;

		// 飞机移动时造成的选择
		airplane.mesh.rotation.z = (targetY - airplane.mesh.position.y) * game.planeRotXSensivity;
		airplane.mesh.rotation.x = (airplane.mesh.position.y - targetY) * game.planeRotZSensivity;
		camera.fov = normalize(mousePos.x, -1, 1, 55, 45);
		camera.updateProjectionMatrix()
		// 摄像机高度变化（跟着飞机）
		camera.position.y += (airplane.mesh.position.y - camera.position.y) * game.cameraSensivity;

		// 飞机碰撞后偏移的恢复
		game.planeCollisionSpeedX += (0 - game.planeCollisionSpeedX) * 0.48;
		game.planeCollisionDisplacementX += (0 - game.planeCollisionDisplacementX) * 0.16;
		game.planeCollisionSpeedY += (0 - game.planeCollisionSpeedY) * 0.48;
		game.planeCollisionDisplacementY += (0 - game.planeCollisionDisplacementY) * 0.16;
	}
	// 更新距离
	updateDistance() {
		game.distance += game.speed * game.ratioSpeedDistance;
		this.fieldDistance.innerHTML = Math.floor(game.distance);
		// 距离的圈DOM 更新数据
		const d = 502 * (1 - (game.distance % game.distanceForLevelUpdate) / game.distanceForLevelUpdate);
		this.levelCircle.setAttribute("stroke-dashoffset", d);
	}
	// 更新血量
	updateEnergy() {
		const energyBar = this.energyBar

		// 每帧扣血
		game.energy -= game.speed * game.ratioSpeedEnergy;
		game.energy = Math.max(0, game.energy);
		energyBar.style.right = (100 - game.energy) + "%";
		energyBar.style.backgroundColor = game.energy < 50 ? "#f25346" : "#68c3c0";
		energyBar.style.animationName = game.energy < 30 ? "blinking" : "none";

		game.energy < 1 && (game.status = "gameover");
	}

	// 全局碰撞检测
	collisionDetection() {
		const airplane = this.airplane
		const ennemiesInUse = this.ennemiesHolder.inUse
		const ennemiesPool = this.ennemiesHolder.pool
		const coinsInUse = this.coinsHolder.inUse
		const coinsPool = this.coinsHolder.pool

		// 飞机石头碰撞
		for (let i = 0; i < ennemiesInUse.length; i++) {
			const ennemy = ennemiesInUse[i];
			const diffPos = airplane.mesh.position.clone().sub(ennemy.mesh.position.clone());
			const d = diffPos.length();
			if (d < game.ennemyDistanceTolerance) {
				// 添加破碎特效
				this.particlesHolder.spawnParticles(ennemy.mesh.position.clone(), 15, Colors.red, 3);

				// 删除石头实例
				ennemiesPool.unshift(ennemiesInUse.splice(i, 1)[0]);
				this.ennemiesHolder.mesh.remove(ennemy.mesh);
				// 碰撞后造成了xy轴的加速度（飞机后退）
				game.planeCollisionSpeedX = 100 * diffPos.x / d;
				game.planeCollisionSpeedY = 100 * diffPos.y / d;
				// 被撞了后，环境光强度变成2（亮了）
				this.ambientLight.intensity = 2;
				// 扣血
				game.energy -= game.ennemyValue;
				game.energy = Math.max(0, game.energy);
				i--;
			}
		}

		// 飞机硬币碰撞
		for (let i = 0; i < coinsInUse.length; i++) {
			const coin = coinsInUse[i];
			const diffPos = airplane.mesh.position.clone().sub(coin.mesh.position.clone());
			const d = diffPos.length();
			if (d < game.coinDistanceTolerance) {
				// 添加破碎特效
				this.particlesHolder.spawnParticles(coin.mesh.position.clone(), 5, 0x009999, .8);

				// 删除硬币实例
				coinsPool.unshift(coinsInUse.splice(i, 1)[0]);
				this.coinsHolder.mesh.remove(coin.mesh);
				// 加血
				game.energy += game.coinValue;
				game.energy = Math.min(game.energy, 100);
				i--;
			}
		}
	}

	// 游戏逻辑更新主函数
	update() {
		// fps
		const newTime = new Date().getTime();
		if (newTime - databus.oldTime > 1000) {
			this.gameFps.innerHTML = 'fps: ' + databus.fpsValue
			databus.fpsValue = 0
			databus.oldTime = newTime;
		} else {
			databus.fpsValue++
		}

		const airplane = this.airplane

		if (game.status === "playing") {
			// 创建硬币（每100米创建）
			if (Math.floor(game.distance) % game.distanceForCoinsSpawn === 0 && Math.floor(game.distance) > game.coinLastSpawn) {
				game.coinLastSpawn = Math.floor(game.distance);
				this.coinsHolder.spawnCoins();
			}

			// 更新基础速度（每100米加速）
			if (Math.floor(game.distance) % game.distanceForSpeedUpdate === 0 && Math.floor(game.distance) > game.speedLastUpdate) {
				game.speedLastUpdate = Math.floor(game.distance);
				game.targetBaseSpeed += game.incrementSpeedByTime;
			}

			// 创建石头（每50米创建）
			if (Math.floor(game.distance) % game.distanceForEnnemySpawn === 0 && Math.floor(game.distance) > game.ennemyLastSpawn) {
				game.ennemyLastSpawn = Math.floor(game.distance);
				this.ennemiesHolder.spawnEnnemy();
			}

			// 难度提升（每1000米升级）
			if (Math.floor(game.distance) % game.distanceForLevelUpdate === 0 && Math.floor(game.distance) > game.levelLastUpdate) {
				game.levelLastUpdate = Math.floor(game.distance);
				game.level++;
				this.fieldLevel.innerHTML = Math.floor(game.level);

				game.targetBaseSpeed = game.initSpeed + game.incrementSpeedByLevel * game.level
			}


			this.updatePlane();
			this.updateDistance();
			this.updateEnergy();

			// 游戏速度更新
			game.baseSpeed += (game.targetBaseSpeed - game.baseSpeed) * 0.02;
			game.speed = game.baseSpeed * game.planeSpeed;

		} else if (game.status === "gameover") {
			game.speed *= .99; // 速度慢慢减慢

			// 飞机坠落（坠落旋转）
			airplane.mesh.rotation.z += (-Math.PI / 2 - airplane.mesh.rotation.z) * .0032;
			airplane.mesh.rotation.x += 0.0048;
			game.planeFallSpeed *= 1.05;
			airplane.mesh.position.y -= game.planeFallSpeed;

			// 坠落结束
			if (airplane.mesh.position.y < -200) {
				this.replayMessage.style.display = "block";
				game.status = "waitingReplay";
			}
		} else if (game.status === "waitingReplay") { }


		// 环境光强度接近0.5
		this.ambientLight.intensity += (.5 - this.ambientLight.intensity) * 0.08;


		airplane.update(); // 飞行动画（螺旋桨转动，旗子飘动）

		this.coinsHolder.update(); // 硬币前进和自转
		this.ennemiesHolder.update(); // 石头前进和自转

		this.sky.update(); // 移动云
		this.sea.update(); // 海洋动画（变换海浪，海洋前进）


		this.collisionDetection(); // 碰撞检测
	}

	// 帧循环
	loop() {
		this.update()
		this.renderer.render(this.scene, this.camera); // 渲染
		requestAnimationFrame(this.loop.bind(this));
	}
}


// 值的转换
// v 范围 vmin-vmax，得到值 tmin-tmax
function normalize(v, vmin, vmax, tmin, tmax) {
	const nv = Math.max(Math.min(v, vmax), vmin);
	const dv = vmax - vmin;
	const pc = (nv - vmin) / dv;
	const dt = tmax - tmin;
	const tv = tmin + (pc * dt);
	return tv;
}
